"""DesktopAutomation类 - 提供桌面自动化功能"""

import os
import time
import pyautogui
import pygetwindow as gw
import cv2
import numpy as np
from typing import Tuple, List, Optional, Union

from rpa_framework.rpa_logging.logger import Logger
from rpa_framework.exceptions.rpa_exceptions import ElementNotFoundException, ImageNotFoundException

class DesktopAutomation:
    """桌面自动化类，提供鼠标、键盘控制和图像识别功能"""
    
    def __init__(self, screenshot_dir: str = "./screenshots"):
        """初始化桌面自动化
        
        Args:
            screenshot_dir: 截图保存目录
        """
        self.logger = Logger("DesktopAutomation")
        self.screenshot_dir = screenshot_dir
        
        # 设置pyautogui配置
        pyautogui.PAUSE = 0.1  # 操作间隔
        pyautogui.FAILSAFE = True  # 启用故障安全
        
        # 创建截图目录
        if not os.path.exists(screenshot_dir):
            os.makedirs(screenshot_dir)
    
    def move_mouse(self, x: int, y: int, duration: float = 0.2) -> None:
        """移动鼠标到指定位置
        
        Args:
            x: X坐标
            y: Y坐标
            duration: 移动持续时间（秒）
        """
        self.logger.debug(f"移动鼠标到: ({x}, {y})")
        pyautogui.moveTo(x, y, duration=duration)
    
    def click(self, x: int = None, y: int = None, clicks: int = 1, button: str = 'left') -> None:
        """点击鼠标
        
        Args:
            x: X坐标（可选）
            y: Y坐标（可选）
            clicks: 点击次数
            button: 按钮类型 ('left', 'right', 'middle')
        """
        click_info = f"点击{clicks}次" + (f" 鼠标{button}键" if button != 'left' else "")
        
        if x is not None and y is not None:
            click_info += f" 在位置: ({x}, {y})"
            pyautogui.click(x, y, clicks=clicks, button=button)
        else:
            pyautogui.click(clicks=clicks, button=button)
        
        self.logger.debug(click_info)
    
    def double_click(self, x: int = None, y: int = None, button: str = 'left') -> None:
        """双击鼠标
        
        Args:
            x: X坐标（可选）
            y: Y坐标（可选）
            button: 按钮类型 ('left', 'right', 'middle')
        """
        self.click(x, y, clicks=2, button=button)
    
    def right_click(self, x: int = None, y: int = None) -> None:
        """右键点击
        
        Args:
            x: X坐标（可选）
            y: Y坐标（可选）
        """
        self.click(x, y, button='right')
    
    def drag_to(self, x: int, y: int, duration: float = 0.5, button: str = 'left') -> None:
        """拖拽鼠标到指定位置
        
        Args:
            x: X坐标
            y: Y坐标
            duration: 拖拽持续时间（秒）
            button: 按钮类型
        """
        self.logger.debug(f"拖拽到位置: ({x}, {y})")
        pyautogui.dragTo(x, y, duration=duration, button=button)
    
    def press(self, key: str or List[str], presses: int = 1, interval: float = 0.0) -> None:
        """按下并释放按键
        
        Args:
            key: 键名或键名列表
            presses: 按键次数
            interval: 多次按键之间的间隔时间
        """
        self.logger.debug(f"按键: {key}, 次数: {presses}")
        pyautogui.press(key, presses=presses, interval=interval)
    
    def hotkey(self, *args) -> None:
        """按下组合键
        
        Args:
            *args: 键名列表
        """
        self.logger.debug(f"按下组合键: {args}")
        pyautogui.hotkey(*args)
    
    def typewrite(self, text: str, interval: float = 0.0) -> None:
        """输入文本
        
        Args:
            text: 要输入的文本
            interval: 字符间间隔时间
        """
        self.logger.debug(f"输入文本: {text}")
        pyautogui.typewrite(text, interval=interval)
    
    def screenshot(self, filename: str = None) -> np.ndarray:
        """截图
        
        Args:
            filename: 保存文件名（可选）
            
        Returns:
            截图的numpy数组
        """
        screenshot = pyautogui.screenshot()
        screenshot_np = np.array(screenshot)
        
        # 如果提供了文件名，保存截图
        if filename:
            filepath = os.path.join(self.screenshot_dir, filename)
            screenshot.save(filepath)
            self.logger.debug(f"截图已保存: {filepath}")
        
        return screenshot_np
    
    def find_image(self, image_path: str, confidence: float = 0.8) -> Tuple[int, int] or None:
        """在屏幕上查找图像
        
        Args:
            image_path: 要查找的图像路径
            confidence: 匹配阈值
            
        Returns:
            找到的图像中心坐标 (x, y)，未找到返回None
            
        Raises:
            ImageNotFoundException: 找不到指定的图像文件
        """
        if not os.path.exists(image_path):
            raise ImageNotFoundException(f"找不到图像文件: {image_path}")
        
        self.logger.debug(f"查找图像: {image_path}, 匹配阈值: {confidence}")
        
        try:
            location = pyautogui.locateCenterOnScreen(image_path, confidence=confidence)
            return location
        except Exception as e:
            self.logger.warning(f"查找图像失败: {str(e)}")
            return None
    
    def click_image(self, image_path: str, confidence: float = 0.8, clicks: int = 1) -> bool:
        """点击屏幕上的图像
        
        Args:
            image_path: 要点击的图像路径
            confidence: 匹配阈值
            clicks: 点击次数
            
        Returns:
            成功点击返回True，未找到图像返回False
        """
        location = self.find_image(image_path, confidence)
        
        if location:
            self.click(location[0], location[1], clicks=clicks)
            return True
        else:
            self.logger.error(f"未找到图像: {image_path}")
            return False
    
    def wait_for_image(self, image_path: str, timeout: int = 10, confidence: float = 0.8) -> Tuple[int, int]:
        """等待图像出现
        
        Args:
            image_path: 要等待的图像路径
            timeout: 超时时间（秒）
            confidence: 匹配阈值
            
        Returns:
            图像中心坐标
            
        Raises:
            ElementNotFoundException: 超时未找到图像
        """
        start_time = time.time()
        
        while time.time() - start_time < timeout:
            location = self.find_image(image_path, confidence)
            if location:
                return location
            time.sleep(0.5)
        
        raise ElementNotFoundException(f"超时未找到图像: {image_path}")
    
    def get_window(self, title: str) -> gw.Window:
        """获取窗口
        
        Args:
            title: 窗口标题（支持部分匹配）
            
        Returns:
            窗口对象
            
        Raises:
            ElementNotFoundException: 找不到窗口
        """
        windows = gw.getWindowsWithTitle(title)
        
        if not windows:
            raise ElementNotFoundException(f"找不到窗口: {title}")
        
        return windows[0]
    
    def activate_window(self, title: str) -> None:
        """激活窗口
        
        Args:
            title: 窗口标题
        """
        window = self.get_window(title)
        window.activate()
        self.logger.debug(f"激活窗口: {title}")
    
    def close_window(self, title: str) -> None:
        """关闭窗口
        
        Args:
            title: 窗口标题
        """
        window = self.get_window(title)
        window.close()
        self.logger.debug(f"关闭窗口: {title}")
    
    def minimize_window(self, title: str) -> None:
        """最小化窗口
        
        Args:
            title: 窗口标题
        """
        window = self.get_window(title)
        window.minimize()
        self.logger.debug(f"最小化窗口: {title}")
    
    def maximize_window(self, title: str) -> None:
        """最大化窗口
        
        Args:
            title: 窗口标题
        """
        window = self.get_window(title)
        window.maximize()
        self.logger.debug(f"最大化窗口: {title}")
    
    def get_window_position(self, title: str) -> Tuple[int, int, int, int]:
        """获取窗口位置和大小
        
        Args:
            title: 窗口标题
            
        Returns:
            (left, top, width, height)
        """
        window = self.get_window(title)
        return (window.left, window.top, window.width, window.height)
    
    def set_window_position(self, title: str, left: int, top: int, width: int = None, height: int = None) -> None:
        """设置窗口位置和大小
        
        Args:
            title: 窗口标题
            left: 左边界
            top: 上边界
            width: 宽度（可选）
            height: 高度（可选）
        """
        window = self.get_window(title)
        window.moveTo(left, top)
        
        if width is not None and height is not None:
            window.resizeTo(width, height)
        
        self.logger.debug(f"设置窗口 {title} 位置: ({left}, {top}) 大小: {width}x{height}")
    
    def wait(self, seconds: float) -> None:
        """等待指定时间
        
        Args:
            seconds: 等待时间（秒）
        """
        self.logger.debug(f"等待 {seconds} 秒")
        time.sleep(seconds)
    
    def get_screen_size(self) -> Tuple[int, int]:
        """获取屏幕尺寸
        
        Returns:
            (width, height)
        """
        return pyautogui.size()
    
    def get_mouse_position(self) -> Tuple[int, int]:
        """获取当前鼠标位置
        
        Returns:
            (x, y)
        """
        return pyautogui.position()

if __name__ == "__main__":
    # 示例用法
    desktop = DesktopAutomation()
    # 打印鼠标位置
    print(f"当前鼠标位置: {desktop.get_mouse_position()}")
    # 打印屏幕尺寸
    print(f"屏幕尺寸: {desktop.get_screen_size()}")
    # 截图
    desktop.screenshot("test_screenshot.png")